package com.song.tools.log.operatelog.util;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * JacksonUtil类提供了使用Jackson库进行JSON序列化和反序列化的方法。
 * Jackson是一个流行的Java库，用于处理JSON数据。
 *
 * @author song tools
 * @since 2024-07-03
 */
@SuppressWarnings("all")
public class JacksonUtil {

    static ObjectMapper defaultMapper() {
        return new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * Unmarshal json string to a target type object
     */
    public static <T> T unmarshal(String json, Class<T> target) {
        T val = null;
        try {
            val = defaultMapper().readValue(json, target);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return val;
    }

    /**
     * Unmarshal json string to a list of target type objects
     */
    public static <T> List<T> unmarshalList(String json, Class<T> clazz) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            ObjectMapper mapper = defaultMapper();
            CollectionType javaType = mapper.getTypeFactory()
                    .constructCollectionType(List.class, clazz);
            List<T> val = mapper.readValue(json, javaType);
            return val;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T unmarshalTypeRef(String json, TypeReference<T> typeRef) {
        try {
            ObjectMapper mapper = defaultMapper();
            T val = mapper.readValue(json, typeRef);
            return val;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Marshall
     */
    public static String marshal(Object target) {
        try {
            return defaultMapper().writeValueAsString(target);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> List<T> arrayfromJson(String jsonStr, Class<T> clazz) {
        ObjectMapper mapper = getObjectMapper();
        JavaType javaType = mapper.getTypeFactory().constructParametricType(ArrayList.class, clazz);

        List<T> readValue = null;
        try {
            readValue = mapper.readValue(jsonStr, javaType);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return readValue;
    }

    private static ObjectMapper getObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();

        // 在遇到未知属性的时候不抛出异常
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        // 输出 json 时，如果值为 null，则忽略
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        return mapper;
    }

    /**
     * 数据类型兼容
     */
    public  static JSONObject changeJsonType(JSONObject jsonObject, Class clazz) {
        Field[] fields = clazz.getFields();
        Object value;
        String fieldName;
        for (Field field : fields) {
            field.setAccessible(true);
            if (field.getType() == Long.class) {
                fieldName = field.getName();
                value = jsonObject.get(fieldName);
                jsonObject.put(fieldName, value != null && !"".equals(value) ? Long.parseLong(value + "") : 0L);
            }
            if (field.getType() == Integer.class) {
                fieldName = field.getName();
                value = jsonObject.get(fieldName);
                jsonObject.put(fieldName, value != null && !"".equals(value) ? Integer.parseInt(value + "") : 0);
            }
        }
        return jsonObject;
    }

    /**
     * 对象转json字符串
     */
    public static String toJSONString(Object o) {
       return JSONObject.toJSONString(o);
    }
}
